/*
 * Copyright 2013 Pavel Stastny <pavel.stastny at gmail.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.aplikator.server.descriptor;

import org.aplikator.client.shared.descriptor.FormDTO;
import org.aplikator.client.shared.descriptor.WizardPageDTO;
import org.aplikator.server.Context;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.aplikator.client.shared.data.Record;

/**
 *
 * @author Pavel Stastny <pavel.stastny at gmail.com>
 */
public class WizardPage extends ServerDescriptorBase {
    
    private List<Property<? extends Serializable>> properties = new ArrayList<Property<? extends Serializable>>();

    private Form form = null;
    
    private Function function;

    private boolean hasNext = false;
    private boolean hasPrevious = false;
    private boolean hasExecute = true;
    
    private String pageId;
    private Record clientRecord;
    
    public WizardPage(Function function, String id) {
        super(function.getId().substring(function.getId().indexOf(TYPE_DELIMITER) + 1) + SUFFIX_DELIMITER + id);
        this.pageId = id;
        this.function = function;
        this.function.registerWizardPage(id, this);
        this.setLocalizationKey(function.getLocalizationKey() + "." + id);
    }


    public List<Property<? extends Serializable>> getProperties() {
        return properties;
    }

    /*public Wizard addProperty(Property<? extends Serializable> property) {
        Preconditions.checkArgument(property!=null, "Attempted to add null property to wizard: "+this);
        properties.add(property);
        return this;
    } */

    private <X extends Serializable> Property<X> addProperty(String name, Class<X> type, double size, boolean required) {
        Property<X> property = new Property<X>(this.getId() + "." + name, type, size, required, null);
        property.setLocalizationKey(this.getId() + "." + name);
    
        for (Property<? extends Serializable> prop : properties) {
            if (prop.getId().equals(property.getId())) 
                throw new IllegalStateException("property with "+prop.getId()+" already defined");
        }
        
        properties.add(property);
        return property;
    }

    public Property<String> stringProperty(String name, int size, boolean required) {
        return addProperty(name, String.class, size, required);
    }

    public Property<String> stringProperty(String name, int size) {
        return stringProperty(name, size, false);
    }

    public Property<String> stringProperty(String name) {
        return stringProperty(name, 255);
    }

    public Property<String> textProperty(String name) {
        return addProperty(name, String.class, 0, false);
    }

    public Property<Boolean> booleanProperty(String name, boolean required) {
        return addProperty(name, Boolean.class, 0, required);
    }

    public Property<Boolean> booleanProperty(String name) {
        return booleanProperty(name, false);
    }

    public Property<BigDecimal> numericProperty(String name, double size, boolean required) {
        return addProperty(name, BigDecimal.class, size, required);
    }

    public Property<BigDecimal> numericProperty(String name) {
        return numericProperty(name, 10.2, false);
    }

    public Property<Integer> integerProperty(String name, boolean required) {
        return addProperty(name, Integer.class, 10.0, required);
    }

    public Property<Integer> integerProperty(String name) {
        return integerProperty(name, false);
    }

    public Property<Date> dateProperty(String name, boolean required) {
        return addProperty(name, Date.class, 0, required);
    }

    public Property<Date> dateProperty(String name) {
        return dateProperty(name, false);
    }


    public WizardPageDTO getViewDTO(Context ctx) {
        WizardPageDTO vdto = new WizardPageDTO(this.getId(), this.getLocalizedName(ctx));
        for (Property<? extends Serializable> p : this.properties) {
            vdto.addProperty(p.clientClone(ctx));
        }
        vdto.setHasExecute(this.hasExecute);
        vdto.setHasNext(this.hasNext);
        vdto.setHasPrevious(this.hasPrevious);
        vdto.setFormDescriptor(createFormDescriptor(ctx));
        vdto.setPageId(this.pageId);
        vdto.setClientRecord(this.clientRecord);
        return vdto;
    }

    private FormDTO createFormDescriptor(Context ctx) {
        Form f = this.form;
        FormDTO retval = new FormDTO(f.getId(), f.getLocalizedName(ctx), f.isHorizontal());
        retval.setLayout(f.getLayout().getWidgetDescriptor(ctx));
        return retval;
    }

    /*
    public Form getForm(String key, Context) {
        return this.forms.get(key);
    }*/
    

    /*
    public Form[] getForm(Context context) {
        return form;
    }

    public Wizard setForm(Form[] form) {
        this.form = form;
        return this;
    }*/
    
    public WizardPage setForm(Form f) {
        this.form = f;
        return this;
    }

    public WizardPage form( Widget layout, boolean horizontal) {
        return setForm(Form.form(layout, horizontal));
    }

    public boolean isHasNext() {
        return hasNext;
    }

    public boolean isHasPrevious() {
        return hasPrevious;
    }

    public boolean isHasExecute() {
        return hasExecute;
    }

    public void setHasNext(boolean hasNext) {
        this.hasNext = hasNext;
    }

    public void setHasPrevious(boolean hasPrevious) {
        this.hasPrevious = hasPrevious;
    }

    public void setHasExecute(boolean hasExecute) {
        this.hasExecute = hasExecute;
    }

    public String getPageId() {
        return pageId;
    }

    public Record getClientRecord() {
        return clientRecord;
    }

    public void setClientRecord(Record clientRecord) {
        this.clientRecord = clientRecord;
    }
}
